home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
bss
/
pup.arc
/
EDIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-12-11
|
6KB
|
201 lines
#include <puppy.h>
#include <pupmem.h>
#include <ascii.h>
/*
Miserable Message Editor
T. Jennings
Fido Software
164 Shipley
San Francisco CA 94107
(415)-764-1688
(k) all rights reversed
*/
#define WIDOFF (sizeof("99: ")) /* size of line number prompt */
/* Enter and edit text. */
edit(ln)
int ln; /* first line to input at, */
{
int end; /* maximum line # */
int lastline; /* last line number, for detecting when to display */
char *cp,c;
char rptchar; /* repeat-last-char count */
char *tp; /* ptr to the text buffer itself */
char word[SS * 2]; /* word[] must be at least 2X max line len */
FLAG run; /* 1 == keep inputting, etc */
int pw; /* length of 'word' (index into word[]) */
int tw; /* length of 'tp' (index into text line) */
end= pup.msgsize / width; /* maximum lines */
tp= &text[ln * width]; /* ptr to the text */
tw= 0; /* length of current line */
lastline= -1; /* trigger line # display */
rptchar= 0; /* no character repeat count */
ins_line(ln,end); /* incase we're I)nserting */
run= 1;
while ( run && (ln < end)) {
if (ln != lastline) {
lastline= ln; /* only once each line */
line= 0; /* override "More?" */
mconout(CR); mconout(LF); /* prevent autowrap */
mprintf("%2u: ",ln + 1); /* display line number */
for (cp= tp; *cp; ++cp) { /* display line so far */
if (*cp >= ' ') mconout(*cp);
}
}
/* OK, now build a 'word', character by character. We stop (unbeknownst
to the user) when we get a CR, space, etc. We also "fall out" if the word
becomes too long to fit on the screen; hence the "while strlen + pc < width". */
pw= 0;
while (tw + pw + WIDOFF < width) { /* while it fits the line ... */
if (rptchar != 0) { /* if repeated character */
--rptchar; /* count one, */
} else c= mconin(); /* get one word */
if ((c == SUB) || (c == VT) || (c == ETX)) {
run= 0; /* if ^Z, ^K or ^C */
break; /* stop editing */
}
if (c == CR) break; /* stop if CR, */
if (c == DEL) c= BS; /* DEL becomes BS */
if (c == TAB) { /* if we get a tab, */
rptchar= 8 - ((tw + pw) % 8); /* count = column mod 8 */
c= ' '; /* set the character, */
continue; /* then go do it */
}
if (c == CAN) { /* if delete line */
rptchar= tw + pw; /* for the entire line, */
c= BS; /* set as back space, */
continue; /* go do it */
}
/* If a character delete, backspace on the screen. First delete characters
from the word we are building, if that is empty, then from the line we
are building. */
if (c == BS) {
if (pw > 0) --pw; /* remove chars from the word, */
else if (tw > 0) --tw; /* or the line, */
else continue; /* (neither, ignore BS) */
erase(1); /* then erase on screen */
mconout(BS);
continue;
}
if (c >= ' ') {
mconout(c);
word[pw++]= c; /* store chars in word */
}
if (pw >= sizeof(word) - 1) break; /* max length */
if (c == TAB) break; /* word terminators */
if (c == ' ') break;
if (c == ',') break;
if (c == ';') break;
}
word[pw]= NUL; /* terminate the word */
tp[tw]= NUL; /* and the line so far */
/* We have text on the screen, and a word in the word[] array. If it will
fit within the screen line length, display as-is, if not, do a CR/LF and
do it on the next line. (This gets executed when word[] is zero length,
ie. only a CR is entered.) */
if (tw + pw + WIDOFF < width) {
strcat(tp,word); /* add it if it fits, */
tw += pw; /* current line length, */
/* When we go to the next line, insert a blank line; if we're entering
new text this is a waste of time, but if we're inserting it moves existing
text down one line. */
} else { /* doesnt fit */
erase(pw); /* clear last word from screen, */
if (tw == 0) strcat(tp," "); /* no 0 length lines */
tp += width; /* go to next line */
++ln; /* next line # */
ins_line(ln,end); /* insert a blank one, */
strcpy(tp,word); /* put word on next line, */
tw= pw; /* also its line length */
}
/* If a CR was entered, then we want to force things to start on the next
line. Also stuff a CR when the line is ended if its not a blank line by itself. */
if (c == CR) { /* if hard return */
strcat(tp,"\r\n"); /* add a CR/LF */
tp += width; /* next line */
++ln; /* next line # */
ins_line(ln,end); /* insert a blank one, */
tw= 0; /* new line is blank */
}
}
if ( ! *tp) strcpy(tp,"\r\n");
/* Now find the first unused line, and return that as the next line. */
while (*tp) { /* find next blank line */
if (ln >= end) break; /* dont go past the end */
tp += width;
++ln;
}
return(ln);
}
/* Delete a line from the text array. */
del_line(line,end)
int line,end;
{
char *tp;
tp= &text[line * width]; /* ptr to 1st line */
while (line < end) {
strcpy(tp,tp + width); /* copy the line, */
tp += width; /* next ... */
++line;
}
*tp= NUL; /* last line is empty */
return(--end);
}
/* Insert a blank line. Copies all lines down one, dropping
off one at the bottom (which is presumably blank.) */
ins_line(line,end)
int line,end;
{
char *tp;
int i;
tp= &text[end * width]; /* tp == address of last line, */
for (i= end - line; i; --i) {
strcpy(tp,tp - width); /* copy line down, */
tp -= width; /* next ... */
}
*tp= NUL; /* inserted line is empty */
return(end);
}
/* Erase a word. Backspace, then type spaces. */
erase(n)
int n;
{
int i;
for (i= 0; i < n; i++) mconout(BS);
for (i= 0; i < n; i++) mconout(' ');
}